#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <pthread.h>
#include "common.h"

void *client_thread(void *arg) 
{
	int clientfd = *(int *)arg;
	int ret;

	pthread_detach(pthread_self());

	while(1)
	{
		char buf[1024] = {0};
		ret = recv_msg(clientfd,buf);
		if(ret < 0)
		{
			break;
		}

		ret = server_process_msg(clientfd,buf);
		if(ret < 0)
		{
			break;
		}
	}

	close(clientfd);
	printf("Client disconnected:%d\n",clientfd);
	return	NULL;
}

int main(int argc,char *argv[])
{
	if(argc != 2)
	{
		printf("usage %s port\n",argv[0]);
		return -1;
	}

	int listenfd,newfd;
	int ret;
	struct sockaddr_in saddr,caddr;
	int on = 1;
	socklen_t addrlen = sizeof(saddr);

	if(database_init() != 0) {
		return -1;
	}

	listenfd = socket(AF_INET,SOCK_STREAM,0);
	if(listenfd < 0)
	{
		perror("socket failed");
		return -1;
	}

	setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));

	memset(&saddr,0,sizeof(saddr));
	saddr.sin_family = AF_INET;
	saddr.sin_port = htons(atoi(argv[1]));
	saddr.sin_addr.s_addr = INADDR_ANY;

	ret = bind(listenfd,(struct sockaddr *)&saddr,sizeof(saddr));
	if(ret < 0)
	{
		perror("bind failed");
		close(listenfd);
		return -1;
	}

	ret = listen(listenfd,5);
	if(ret < 0)
	{
		perror("listen failed");
		close(listenfd);
		return -1;
	}

	printf("Server started on port %s\n", argv[1]); 

	while(1) {
		newfd = accept(listenfd, (struct sockaddr*)&caddr, &addrlen);
		if(newfd < 0) {
			perror("accept failed");
			continue;
		}

		printf("New connection from %s:%d\n", inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port));

		pthread_t tid;
		int *clientfd = malloc(sizeof(int));
		*clientfd = newfd;

		if(pthread_create(&tid, NULL, client_thread, clientfd) != 0) {
			perror("pthread_create failed");
			close(newfd);
			free(clientfd);
		}


	}
	close(listenfd);
	return 0;
}
